use std::{collections::BTreeMap, env::var_os, path::PathBuf, process::Command, str::FromStr};

#[cfg(target_os = "windows")]
pub(super) fn run() {
    // envs
    let env_titles = [
        "APPDATA",
        "LOCALAPPDATA",
        "TEMP",
        "XDG_DATA_HOME",
        "XDG_CACHE_HOME",
        "XDG_CONFIG_HOME",
        "LUNARVIM_RUNTIME_DIR",
        "LUNARVIM_CONFIG_DIR",
        "LUNARVIM_CACHE_DIR",
        "LUNARVIM_BASE_DIR",
    ];
    let envs: Vec<_> = env_titles
        .iter()
        .filter_map(|title| var_os(title).map(|val| (*title, val)))
        .filter_map(|(title, var)| {
            PathBuf::from_str(var.to_string_lossy().as_ref())
                .map(|dir| (title, dir))
                .map_err(|err| dbg!(err))
                .ok()
        })
        .filter(|(_, dir)| dir.is_dir())
        .collect();
    let mut envs_map = BTreeMap::from_iter(envs);
    // Find xdg
    if !envs_map.contains_key("XDG_DATA_HOME") {
        envs_map.insert(
            "XDG_DATA_HOME",
            envs_map
                .get("APPDATA")
                .filter(|dir| dir.is_dir())
                .map(|xdg_data_home| xdg_data_home.to_path_buf())
                .expect("APPDATA NOT FOUND"),
        );
    }
    if !envs_map.contains_key("XDG_CONFIG_HOME") {
        envs_map.insert(
            "XDG_CONFIG_HOME",
            envs_map
                .get("LOCALAPPDATA")
                .filter(|dir| dir.is_dir())
                .map(|xdg_data_home| xdg_data_home.to_path_buf())
                .expect("LOCALAPPDATA NOT FOUND"),
        );
    }
    if !envs_map.contains_key("XDG_CACHE_HOME") {
        envs_map.insert(
            "XDG_CACHE_HOME",
            envs_map
                .get("TEMP")
                .filter(|dir| dir.is_dir())
                .map(|xdg_data_home| xdg_data_home.to_path_buf())
                .expect("TEMPAPPDATA NOT FOUND"),
        );
    }
    // Find lunarvim
    if !envs_map.contains_key("LUNARVIM_RUNTIME_DIR") {
        envs_map.insert(
            "LUNARVIM_RUNTIME_DIR",
            envs_map
                .get("XDG_DATA_HOME")
                .filter(|dir| dir.is_dir())
                .map(|xdg_data_home| xdg_data_home.join("lunarvim"))
                .expect("XDG_DATA_HOME NOT FOUND"),
        );
    }
    if !envs_map.contains_key("LUNARVIM_CONFIG_DIR") {
        envs_map.insert(
            "LUNARVIM_CONFIG_DIR",
            envs_map
                .get("XDG_CONFIG_HOME")
                .filter(|dir| dir.is_dir())
                .map(|xdg_config_home| xdg_config_home.join("lvim"))
                .expect("XDG_CONFIG_HOME NOT FOUND"),
        );
    }
    if !envs_map.contains_key("LUNARVIM_CACHE_DIR") {
        envs_map.insert(
            "LUNARVIM_CACHE_DIR",
            envs_map
                .get("XDG_CACHE_HOME")
                .filter(|dir| dir.is_dir())
                .map(|xdg_cache_home| xdg_cache_home.join("lvim"))
                .expect("XDG_CACHE_HOME NOT FOUND"),
        );
    }
    if !envs_map.contains_key("LUNARVIM_BASE_DIR") {
        envs_map.insert(
            "LUNARVIM_BASE_DIR",
            envs_map
                .get("LUNARVIM_RUNTIME_DIR")
                .filter(|dir| dir.is_dir())
                .map(|lunarvim_runtime_dir| lunarvim_runtime_dir.join("lvim"))
                .expect("LUNARVIM_RUNTIME_DIR NOT FOUND"),
        );
    }
    println!("{:#?}", envs_map);
    // Execute
    let _child = Command::new("neovide")
        // .envs(envs)
        .arg("--")
        .args([
            "-u",
            envs_map
                .get("LUNARVIM_BASE_DIR")
                .map(|dir| dir.join("init.lua"))
                .expect("Failed to find LUNARVIM_BASE_DIR!!!")
                .to_string_lossy()
                .as_ref(),
        ])
        .args(std::env::args().skip(1))
        .envs(envs_map)
        .spawn()
        .expect("Failed to spawn neovide!!!");
}
